package com.tanhua.admin.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.tanhua.admin.mapper.AnalysisMapper;
import com.tanhua.admin.mapper.LogMapper;
import com.tanhua.model.db.Analysis;
import com.tanhua.model.vo.AnalysisSummaryVo;
import com.tanhua.model.vo.Year;
import com.tanhua.model.vo.YearVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

@Service
public class AnalysisService {

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private AnalysisMapper analysisMapper;

    /**
     * 数据统计
     */
    public void analysis() {
        Date date = new Date();
        //1. 获取今天与昨天字符串
        String today = DateUtil.today();
        String yesterday = DateUtil.yesterday().toDateStr();
        //2. 统计今日新增用户数
        Integer numRegistered = logMapper.countNumRegisteredToday(today);
        //3. 活跃用户数
        Integer numActive = logMapper.countNumActiveByDate(today);
        //4. 登陆次数
        Integer numLogin = logMapper.countNumLoginByDate(today);
        //5. 次日留存用户数
        Integer numRetention1d = logMapper.countNumRetention1d(today, yesterday);
        //6. 构建pojo
        Analysis pojo = new Analysis();
        pojo.setNumActive(numActive);
        pojo.setNumLogin(numLogin);
        pojo.setNumRetention1d(numRetention1d);
        pojo.setNumRegistered(numRegistered);
        pojo.setUpdated(date);
        //7. 通过日期查询，判断是否存在统计记录
        Analysis analysisInDb = analysisMapper.findByRecordDate(today);
        //8. 存在则更新数量
        if(null != analysisInDb){
            pojo.setId(analysisInDb.getId());
            analysisMapper.updateById(pojo);
        }else {
            //9. 不存在则添加记录
            pojo.setRecordDate(date);
            pojo.setCreated(date);
            analysisMapper.insert(pojo);
        }
    }

    /**
     * 首页统计
     * @return
     */
    public AnalysisSummaryVo summary() {
        Date date = new Date();
        String today = DateUtil.today();
        String yesterday = DateUtil.yesterday().toDateStr();
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        vo.setCumulativeUsers(analysisMapper.totalUser()); //累计用户数
        vo.setActivePassMonth(logMapper.countNumActiveByBetweenDate(DateUtil.offsetDay(date, -30)));
        vo.setActivePassWeek(logMapper.countNumActiveByBetweenDate(DateUtil.offsetDay(date, -7)));

        Long newUsersToday = analysisMapper.countNewUsers(today);
        Long newUsersYesterday = analysisMapper.countNewUsers(yesterday);

        vo.setNewUsersToday(newUsersToday);
        vo.setNewUsersTodayRate(computeRate(newUsersToday, newUsersYesterday));

        Long loginTimesToday = analysisMapper.countLoginTimes(today);
        Long loginTimesYesterday = analysisMapper.countLoginTimes(yesterday);
        vo.setLoginTimesToday(loginTimesToday);
        vo.setLoginTimesTodayRate(computeRate(loginTimesToday, loginTimesYesterday));

        Long activeUsersToday = analysisMapper.countActiveUsers(today);
        Long activeUsersYesterday = analysisMapper.countActiveUsers(yesterday);
        vo.setActiveUsersToday(activeUsersToday);
        vo.setActiveUsersTodayRate(computeRate(activeUsersToday, activeUsersYesterday));

        return vo;
    }

    /**
     * 计算增长率
     * @param current
     * @param last
     * @return
     */
    private BigDecimal computeRate(Long current, Long last) {
        if(last == null || last == 0) {
            return new BigDecimal((current - last) * 100);
        }

        return BigDecimal.valueOf((current-last)*100).divide(BigDecimal.valueOf(last), 2 , RoundingMode.HALF_DOWN);
    }

    /**
     * 新增、活跃用户、次日留存率
     * @param startDate
     * @param endDate
     * @param type
     * @return
     */
    public YearVo analysisUsers(Date startDate, Date endDate, Integer type) {
        switch (type) {
            case 101: {
                List<DateTime> dateTimes = DateUtil.rangeToList(startDate, endDate, DateField.DAY_OF_MONTH);
                Year[] thisYear = new Year[dateTimes.size()];
                Year[] lastYear = new Year[dateTimes.size()];
                int index = 0;
                for (DateTime dateTime : dateTimes) {
                    thisYear[index] = getCountNewUsers(dateTime);
                    dateTime.setField(DateField.YEAR, dateTime.getField(DateField.YEAR)-1);
                    lastYear[index] = getCountNewUsers(dateTime);
                    index++;
                }

                YearVo yearVo = new YearVo();
                yearVo.setThisYear(thisYear);
                yearVo.setLastYear(lastYear);
                return yearVo;
            }

            case 102: {
                List<DateTime> dateTimes = DateUtil.rangeToList(startDate, endDate, DateField.DAY_OF_MONTH);
                Year[] thisYear = new Year[dateTimes.size()];
                Year[] lastYear = new Year[dateTimes.size()];
                int index = 0;
                for (DateTime dateTime : dateTimes) {
                    thisYear[index] = getCountActiveUsers(dateTime);
                    dateTime.setField(DateField.YEAR, dateTime.getField(DateField.YEAR)-1);
                    lastYear[index] = getCountActiveUsers(dateTime);
                    index++;
                }

                YearVo yearVo = new YearVo();
                yearVo.setThisYear(thisYear);
                yearVo.setLastYear(lastYear);
                return yearVo;
            }

            case 103: {
                List<DateTime> dateTimes = DateUtil.rangeToList(startDate, endDate, DateField.DAY_OF_MONTH);
                Year[] thisYear = new Year[dateTimes.size()];
                Year[] lastYear = new Year[dateTimes.size()];
                int index = 0;
                for (DateTime dateTime : dateTimes) {
                    thisYear[index] = getRetention(dateTime);
                    dateTime.setField(DateField.YEAR, dateTime.getField(DateField.YEAR)-1);
                    lastYear[index] = getRetention(dateTime);
                    index++;
                }

                YearVo yearVo = new YearVo();
                yearVo.setThisYear(thisYear);
                yearVo.setLastYear(lastYear);
                return yearVo;
            }
            default: break;
        }
        return null;
    }

    /**
     * 新增用户数
     * @param dateTime
     * @return
     */
    private Year getCountNewUsers(DateTime dateTime) {
        String date = DateUtil.format(dateTime, "yyyy-MM-dd");
        Long count = analysisMapper.countNewUsers(date);
        Year year = new Year();
        year.setTitle(dateTime.dayOfMonth()+"");
        year.setAmount(count.intValue());
        return year;
    }

    /**
     * 用户活跃数
     * @param dateTime
     * @return
     */
    private Year getCountActiveUsers(DateTime dateTime) {
        String date = DateUtil.format(dateTime, "yyyy-MM-dd");
        Long count = analysisMapper.countActiveUsers(date);
        Year year = new Year();
        year.setTitle(dateTime.dayOfMonth()+"");
        year.setAmount(count.intValue());
        return year;
    }

    /**
     * 用户留存率
     * @param dateTime
     * @return
     */
    private Year getRetention(DateTime dateTime) {
        String todayStr = DateUtil.format(dateTime, "yyyy-MM-dd");
        DateTime yesterday = DateUtil.offsetDay(dateTime, -1);
        String yesterdayStr = DateUtil.format(yesterday, "yyyy-MM-dd");
        Long todayRetention = analysisMapper.countNumRetention1d(todayStr);
        Long yesterdayCountNewUsers = analysisMapper.countNewUsers(yesterdayStr);
        Long amount = (todayRetention * 100 / yesterdayCountNewUsers);

        Year year = new Year();
        year.setTitle(dateTime.dayOfMonth() + "");
        year.setAmount(amount.intValue());

        return year;
    }
}

